import React, { useRef, useState, useEffect } from 'react';
import Plyr from 'plyr';
import 'plyr/dist/plyr.css';

const App = () => {
    const videoRef = useRef(null);
    const [mediaSource] = useState(new MediaSource());
    const [sourceBuffer, setSourceBuffer] = useState(null);
    const [currentSegment, setCurrentSegment] = useState(0);
    const [totalSegments, setTotalSegments] = useState(0);
    const segmentSize = 1000000; // 每段大小（字节）
    const [jiazai, setJiazai] = useState([]);
    const jiazaiRef = useRef(jiazai); // 创建 jiazai 的 ref


    const mimeCodec = 'video/mp4; codecs="avc1.64001e, mp4a.40.2"';

    useEffect(() => {
        const player = new Plyr(videoRef.current, {
            controls: ['play-large', 'play', 'progress', 'current-time', 'duration', 'mute', 'volume', 'settings', 'pip', 'fullscreen'],
            settings: ['captions', 'quality', 'speed', 'loop'],
            i18n: {
                speed: '速度',
                normal: '正常',
                quality: '画质',
                loop: '循环',
                rewind: '快退 {seektime}s',
                forward: '快进 {seektime}s',
                seek: '跳转',
                seekLabel: '{currentTime} of {duration}',
                played: '播放了',
                buffered: '缓存',
                currentTime: '当前时间',
                duration: '时长',
                volume: '音量',
                mute: '静音',
                unmute: '取消静音',
                enableCaptions: '启用字幕',
                disableCaptions: '禁用字幕',
                enterFullscreen: '进入全屏',
                exitFullscreen: '退出全屏',
                frameTitle: 'Player for {title}',
                captions: '字幕',
                settings: '设置',
                menuBack: '返回',
                speedLabel: '倍速'
            }
        });

        player.on('play', () => console.log('play'));
        player.on('pause', () => console.log('pause'));
        player.on('ended', () => console.log('ended'));

        // 获取进度条 DOM 元素
        const progressBar = document.querySelector('.plyr__progress');

        const handleProgressBarClick = async (event) => {
            console.log(sourceBuffer, '>>>>>>>>>>')
            if (sourceBuffer.updating) {
                // 如果缓冲正在更新，忽略此次点击
                console.log('Buffer is updating, please wait.');
                return;
            }

            // 用户点击未加载的进度
            console.log(`用户点击了进度条`);
            console.log(totalSegments, '总数')
            console.log(jiazai, '已加载')



            // 获取进度条的宽度和点击位置
            const progressBarWidth = progressBar.clientWidth;
            const clickPosition = event.clientX - progressBar.getBoundingClientRect().left;

            // 计算点击位置对应的段数
            const segmentIndex = Math.floor((clickPosition / progressBarWidth) * totalSegments);
            // 计算点击位置对应的播放时间
            const duration = player.duration; // 获取视频总时长
            const newTime = (clickPosition / progressBarWidth) * duration;
            // 设置视频播放时间
            player.currentTime = newTime;
            console.log(`用户点击了进度条，点击位置对应的段数是: ${segmentIndex}`);

            if (!jiazai.some(item => item === segmentIndex)) {
                let jiazMx = jiazai.sort((a, b) => b - a)[0]

                let newarr = Array(segmentIndex + 1).fill(undefined);
                let req = newarr.map((e, i) => {
                    return new Promise((resolve) => {
                        if (i > jiazMx) {
                            setTimeout(async () => {
                                if (!sourceBuffer.updating && !jiazaiRef.current.some(e => e === i)) {
                                    console.log('请求段', i);
                                    await requestSegment(sourceBuffer, i);
                                }
                                resolve(); // 确保在请求完成后再解析
                            }, 200 * i);
                        } else {
                            resolve(); // 对于已加载的段直接解析
                        }
                    });
                });
                Promise.all(req).then(() => {
                    console.log('加载完成111')

                })
            }

        }

        progressBar.addEventListener('click', handleProgressBarClick);
        return () => {
            // player.destroy();
            progressBar.removeEventListener('click', handleProgressBarClick)
        };
    }, [totalSegments, sourceBuffer, jiazai]);





    useEffect(() => {
        // 判断支持类型
        if (!MediaSource.isTypeSupported(mimeCodec)) {
            console.error('Unsupported codec:', mimeCodec);
            return;
        }
        // 播放器
        const videoElement = videoRef.current;
        // 配置src
        videoElement.src = URL.createObjectURL(mediaSource);
        // 绑定事件
        mediaSource.addEventListener('sourceopen', handleSourceOpen);

        return () => {
            mediaSource.removeEventListener('sourceopen', handleSourceOpen);
            URL.revokeObjectURL(videoElement.src);
        };
    }, [mediaSource]);

    const handleSourceOpen = () => {
        // 添加
        const buffer = mediaSource.addSourceBuffer(mimeCodec);
        // 监听错误
        buffer.onerror = (e) => console.error('SourceBuffer error:', e);
        setSourceBuffer(buffer);
        // 初始化请求第一个段
        requestSegment(buffer, currentSegment); // 请求第一个段

        // 添加 timeupdate 事件监听器
        videoRef.current.addEventListener('timeupdate', () => onTimeUpdate(buffer));
    };


    // 进度条加载
    const onTimeUpdate = (buffer) => {
        const videoElement = videoRef.current;
        const currentTime = videoElement.currentTime;
        const bufferedEnd = buffer.buffered.end(0);
        const preloadThreshold = 2; // 预加载阈值（秒）

        // 检查当前播放时间是否接近缓冲区结束
        if (currentTime >= bufferedEnd - preloadThreshold) {
            setCurrentSegment((prevSegment) => {
                // 获取最新播放段
                const nextSegment = prevSegment + 1;
                if (!jiazaiRef.current.some(e => e === nextSegment)) {
                    requestSegment(buffer, nextSegment);
                    return nextSegment; // 返回更新后的段索引
                } else {
                    return prevSegment;
                }
            });
        }
    };


    // 请求视频数据
    const requestSegment = async (buffer, segment) => {
        // jiazaiRef为请求过的段 最新数据


        if (!buffer || buffer.updating || jiazaiRef.current.some(e => e === segment) || jiazai.some(e => e === segment)) return; // 确保 buffer 不在更新中

        try {
            // 获取总段数
            const sizeResponse = await fetch('http://localhost:3000/sumGetSize');
            if (!sizeResponse.ok) throw new Error('Network response failed');
            const totalSize = await sizeResponse.arrayBuffer();
            const totalBytes = totalSize.byteLength;

            setTotalSegments(Math.ceil(totalBytes / segmentSize)); // 计算总段数
            // 更新已经加载的段
            setJiazai(e => {
                let newarr = [...e, segment]
                jiazaiRef.current = newarr; // 更新 ref 中的最新值
                return newarr
            })

            const start = segment * segmentSize;
            const end = Math.min((segment + 1) * segmentSize - 1, totalBytes - 1);

            const response = await fetch('http://localhost:3000/GetStream', {
                method: 'GET',
                headers: {
                    'Range': `bytes = ${start} -${end} `,
                    'Accept': 'video/mp4',
                },
            });

            if (!response.ok) throw new Error('Network response failed');
            const data = await response.arrayBuffer();
            if (data.byteLength > 0) {
                buffer.appendBuffer(data);
                setCurrentSegment(segment); // 更新当前段索引
            } else {
                console.error('No data fetched');
            }
            return new Promise((resolve) => {
                resolve(data);
            })
        } catch (error) {
            console.error('Error fetching stream:', error);
        }

    };

    return (
        <div>
            <div style={{ width: '800px' }} className='mutation-box'>
                <video ref={videoRef} width={500} id='play' />
            </div>
        </div>
    );
};

export default App;
